package com.nec.recommend.config.jackson;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
import com.fasterxml.jackson.databind.ser.SerializerFactory;

import java.math.BigDecimal;
import java.util.Collection;

/**
 * 空值Value序列化提供器
 * @author songkaikai
 * @since 2022/11/4
 */
public class NullValueSerializerProvider extends DefaultSerializerProvider {

    public NullValueSerializerProvider() {
        super();
    }

    protected NullValueSerializerProvider(SerializerProvider src, SerializationConfig config, SerializerFactory f) {
        super(src, config, f);
    }

    @Override
    public DefaultSerializerProvider createInstance(SerializationConfig config, SerializerFactory jsf) {
        return new NullValueSerializerProvider(this, config, jsf);
    }

    @Override
    public JsonSerializer<Object> getDefaultNullValueSerializer() {
        return super.getDefaultNullValueSerializer();
    }

    @Override
    public JsonSerializer<Object> findNullValueSerializer(BeanProperty property) throws JsonMappingException {
        final NullStringJsonSerializer nullStringJsonSerializer = new NullStringJsonSerializer();
        if (isArrayType(property)) {
            return new ArrayJsonSerializer.NullArrayJsonSerializer();
        } else if (isBigDecimalType(property)) {
            return nullStringJsonSerializer;
        } else if (isBooleanType(property)) {
            return new NullBooleanJsonSerializer();
        } else if (isStringType(property)) {
            return nullStringJsonSerializer;
        }
        return super.findNullValueSerializer(property);
    }

    /**
     * 是否是数组
     */
    private boolean isArrayType(BeanProperty writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return clazz.isArray() || Collection.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是string
     */
    private boolean isStringType(BeanProperty writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return CharSequence.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是boolean
     */
    private boolean isBooleanType(BeanProperty writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return clazz.equals(Boolean.class);
    }

    /**
     * 是否是BigDecimal
     */
    private boolean isBigDecimalType(BeanProperty writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return clazz.equals(BigDecimal.class);
    }
}
